package com.example.testspring.common.tool;

import com.example.testspring.common.annotation.Di;
import com.example.testspring.common.annotation.bean;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName AnnotationApplicationContext
 * @Date 2024/6/2 16:05
 * @Description TODO
 * @User lihuajie
 * @Version 1.0.0
 **/
public class AnnotationApplicationContext implements ApplicationContext{

    private HashMap<Class,Object>  beanFactory = new HashMap<>();
    private static String rootPath;

    @Override
    public Object getBean(Class clazz) {
        return beanFactory.get(clazz);
    }

    public AnnotationApplicationContext(String basePackage) {
        try {
            //将传入的参数文件路径变为正常文件存储时的格式如"com.test.dao"变为"com/test/dao"
            String packDirname = basePackage.replace("//.","////");
            //根据文件路径获取文件下的资源（url路径）
            Enumeration<URL> dirs = Thread.currentThread().getContextClassLoader().getResources(packDirname);
            while (dirs.hasMoreElements()){
                URL url = dirs.nextElement();
                //由于url路径中的部分可能时url编码，使用URLDecoder.decode对其进行解码，确保得到的filepath为编码的路径
                String filePath = URLDecoder.decode(url.getFile(),"utf-8");
                //得到资源的根路径
                rootPath = filePath.substring(0,filePath.length()-packDirname.length());
                loadBean(new File(filePath));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void loadBean(File fileParent){
        if(fileParent.isDirectory()){
            File[] childrenFiles = fileParent.listFiles();
            if(childrenFiles == null || childrenFiles.length == 0){
                return;
            }
            for (File child: childrenFiles){
                if(child.isDirectory()){
                    loadBean(child);
                }else {
                    String pathWithClass = child.getAbsolutePath().substring(rootPath.length()-1);
                    if(pathWithClass.contains(".class")){
                        String fullName = pathWithClass.replaceAll("\\\\", ".").replace(".class", "");
                        try {
                            Class<?> aClass = Class.forName(fullName);
                            //把非接口的类实例化放在map中
                            if(!aClass.isInterface()){
                                bean annotation = aClass.getAnnotation(bean.class);
                                if(annotation != null){
                                    Object instance = aClass.newInstance();
                                    //判断一下有没有接口
                                    if(aClass.getInterfaces().length > 0) {
                                        //如果有接口把接口的class当成key，实例对象当成value
                                        System.out.println("正在加载【"+ aClass.getInterfaces()[0] +"】,实例对象是：" + instance.getClass().getName());
                                        beanFactory.put(aClass.getInterfaces()[0], instance);
                                    }else{
                                        //如果有接口把自己的class当成key，实例对象当成value
                                        System.out.println("正在加载【"+ aClass.getName() +"】,实例对象是：" + instance.getClass().getName());
                                        beanFactory.put(aClass, instance);
                                    }
                                }
                            }
                        }catch (ClassNotFoundException | IllegalAccessException | InstantiationException e){
                            e.printStackTrace();
                        }
                    }
                }
            }
        }

    }

    private void loadDi(){
        //entry是一个键值对
        for(Map.Entry entry : beanFactory.entrySet()){
            Object obj = entry.getValue();
            Class aClass = entry.getClass();
            Field[] fields = aClass.getFields();
            for (Field field : fields){
                Di annocation = field.getAnnotation(Di.class);
                if ( annocation != null){
                    field.setAccessible(true);
                    try {
                        System.out.println("正在给【"+obj.getClass().getName()+"】属性【" + field.getName() + "】注入值【"+ beanFactory.get(field.getType()).getClass().getName() +"】");
                        field.set(obj,beanFactory.get(field.getType()));
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }
    }





}
